import Joi from 'joi';

/**
 * 验证数据
 */
export async function validate<T>(
  data: any,
  schema: Joi.Schema,
): Promise<T> {
  try {
    const value = await schema.validateAsync(data, {
      abortEarly: false,
      stripUnknown: true,
    });
    return value as T;
  } catch (error) {
    if (error instanceof Joi.ValidationError) {
      const errors = error.details.map((detail) => ({
        field: detail.path.join('.'),
        message: detail.message,
      }));
      console.error('Validation errors:', errors);
      console.error('Input data:', JSON.stringify(data, null, 2));
      throw new ValidationError('数据验证失败', errors);
    }
    throw error;
  }
}

/**
 * 自定义验证错误类
 */
export class ValidationError extends Error {
  public errors: Array<{ field: string; message: string }>;

  constructor(message: string, errors: Array<{ field: string; message: string }>) {
    super(message);
    this.name = 'ValidationError';
    this.errors = errors;
  }
}

/**
 * 常用的验证模式
 */
export const commonSchemas = {
  // UUID 验证
  uuid: Joi.string().uuid(),

  // 邮箱验证
  email: Joi.string().email().lowercase().trim(),

  // 密码验证（至少8位，包含大小写字母和数字）
  password: Joi.string()
    .min(8)
    .max(128)
    .pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/)
    .message('密码必须包含至少8位，包括大小写字母和数字'),

  // 分页 - 页码
  page: Joi.number().integer().min(1).optional().default(1),

  // 分页 - 每页数量
  pageSize: Joi.number().integer().min(1).max(100).optional().default(20),

  // 分页参数
  pagination: Joi.object({
    page: Joi.number().integer().min(1).default(1),
    pageSize: Joi.number().integer().min(1).max(100).default(20),
  }),

  // 日期范围
  dateRange: Joi.object({
    startDate: Joi.date().iso(),
    endDate: Joi.date().iso().min(Joi.ref('startDate')),
  }),

  // 子域名验证
  subdomain: Joi.string()
    .lowercase()
    .alphanum()
    .min(3)
    .max(63)
    .pattern(/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/)
    .message('子域名只能包含小写字母、数字和连字符，且不能以连字符开头或结尾'),
};


